Skip to content

feat(hook): add Qoder CLI agent support#1721

Open
sandynz wants to merge 1 commit intortk-ai:developfrom
sandynz:feat/support-qoder-hook
Open

feat(hook): add Qoder CLI agent support#1721
sandynz wants to merge 1 commit intortk-ai:developfrom
sandynz:feat/support-qoder-hook

Conversation

@sandynz
Copy link
Copy Markdown

@sandynz sandynz commented May 5, 2026

Summary

Add rtk init --agent qoder for Qoder CLI integration. Closes #1327.

  • Qoder CLI uses the same PreToolUse JSON protocol as Claude Code, so rtk hook qoder reuses the existing process_claude_payload logic for transparent command rewriting
  • Supports both project-scoped (rtk init --agent qoder.qoder/) and global (rtk init -g --agent qoder~/.qoder/) installation
  • Detects existing workaround hooks (e.g. shell scripts from [Feature] Add Qoder Hook Support #1327) and upgrades them automatically to the native binary
  • Idempotent: running rtk init multiple times never duplicates hook entries or overwrites existing settings

Test plan

  • cargo fmt --all --check && cargo clippy --all-targets && cargo test
    • 1737 tests pass, 0 failures
  • Manual testing: rtk <command> output inspected
    • rtk init --agent qoder — creates RTK.md, patches AGENTS.md, writes .qoder/settings.json
    • rtk init -g --agent qoder — creates ~/.qoder/RTK.md, patches ~/.qoder/settings.json
    • echo '{"tool_name":"Bash","tool_input":{"command":"git status"}}' | rtk hook qoder — returns updatedInput with rtk git status
    • Shell script upgrade: rtk init replaces ~/.qoder/hooks/rtk-qoder-hook.sh with rtk hook qoder
    • Idempotency: running init twice produces "Already installed" / "already up to date" messages
  • Unit tests added for changed code
    • 4 tests in hook_cmd.rs: rewrite Bash, pass-through non-Bash, pass-through already-rtk, pass-through echo
    • 4 tests in init.rs: fresh install, shell script upgrade, idempotency, existing settings preservation
  • Edge cases covered
    • Non-Bash tool calls (e.g. Read) pass through silently
    • Already rtk-prefixed commands pass through
    • Compound commands (&&, ||, |) handled by rewrite_compound()
    • Empty/invalid JSON handled gracefully

Add `rtk init --agent qoder` for Qoder CLI integration.

Qoder CLI uses the same PreToolUse JSON protocol as Claude Code
(tool_input.command + updatedInput), so `rtk hook qoder` reuses
the existing process_claude_payload logic for transparent command
rewriting — no denial, no retry, zero token overhead.

Both project-scoped (`rtk init --agent qoder` → .qoder/) and global
(`rtk init -g --agent qoder` → ~/.qoder/) installations are supported.
The init function detects existing workaround hooks (e.g. shell scripts
from issue rtk-ai#1327) and upgrades them automatically to the native binary.

Changes:
- src/main.rs: Add Qoder to AgentTarget and HookCommands enums
- src/hooks/constants.rs: Add QODER_DIR = ".qoder"
- src/hooks/hook_cmd.rs: Add run_qoder() handler + 4 unit tests
- src/hooks/init.rs: Add run_qoder_mode(), patch_qoder_settings(),
  upgrade detection, idempotent settings.json merging, + 4 unit tests
- hooks/qoder/: README.md + rtk-awareness.md
- hooks/README.md: Add Qoder to supported agents table + JSON format
- src/hooks/README.md: Add Qoder to permission model table
- README.md: Add Qoder CLI to quick start and supported tools table

Closes rtk-ai#1327
@sandynz
Copy link
Copy Markdown
Author

sandynz commented May 5, 2026

Summary

Add rtk init --agent qoder for Qoder CLI integration.

Qoder CLI uses the same PreToolUse JSON protocol as Claude Code
(tool_name/tool_input + updatedInput), so rtk hook qoder reuses
the existing process_claude_payload logic for transparent command
rewriting — no denial, no retry, zero token overhead.

Changes

File Change
src/main.rs Add Qoder to AgentTarget and HookCommands enums, add routing
src/hooks/constants.rs Add QODER_DIR = ".qoder"
src/hooks/hook_cmd.rs Add run_qoder() handler — reuses process_claude_payload
src/hooks/init.rs Add run_qoder_mode() and patch_qoder_settings() with idempotent settings.json merging and workaround upgrade detection
hooks/qoder/README.md Integration documentation
hooks/qoder/rtk-awareness.md Agent-facing awareness instructions
README.md Add Qoder CLI to quick start and supported tools table

Usage

# Project-scoped: writes to .qoder/ (RTK.md + AGENTS.md @RTK.md + settings.json hook)
rtk init --agent qoder

# Global: writes to ~/.qoder/ (RTK.md + settings.json hook)
rtk init -g --agent qoder

How it works

Qoder CLI supports PreToolUse hooks with the same JSON format as Claude Code:

Agent calls: Bash("git status")
  → Qoder CLI fires PreToolUse hook
  → rtk hook qoder reads JSON from stdin
  → Returns hookSpecificOutput.updatedInput.command = "rtk git status"
  → Qoder CLI applies the updated input transparently
  → Agent sees RTK-filtered output directly

Compound commands (with &&, ||, |, ;) are handled by rtk's internal
rewrite_compound() — each segment is rewritten independently, and pipe-incompatible
commands like find/fd are skipped automatically.

Compared to the workaround shell script

Before this PR, Qoder users on #1327 used a custom shell script
(~/.qoder/hooks/rtk-qoder-hook.sh) with a deny-with-suggestion strategy.

Shell script workaround Native --agent qoder
Strategy Deny-with-suggestion (exit 2) Transparent rewrite (updatedInput)
Extra round-trips 1 per command (deny → retry) 0
Dependencies Requires jq None (pure Rust)
Hook command Shell script path in settings.json rtk hook qoder binary
Setup Manual: create script + edit settings.json + rtk init --codex Single command: rtk init --agent qoder
Upgrade path N/A rtk init detects shell script and upgrades automatically

The native integration is strictly better — transparent rewrite eliminates
the extra round-trip, removes the jq dependency, and provides a one-command
setup. The only disadvantage is that users must build from source or wait
for the next rtk release.

Recent enhancements

  • Workaround upgrade detection: if settings.json already has a shell script
    hook (e.g. ~/.qoder/hooks/rtk-qoder-hook.sh), rtk init detects it and
    upgrades to rtk hook qoder automatically, preserving all other settings.

  • Idempotent: running rtk init multiple times never duplicates hook entries
    or overwrites existing settings.json content.

  • Unit tests: 8 tests covering hook rewriting (Bash/non-Bash/already-rtk/echo),
    fresh install, shell script upgrade, idempotency, and config preservation.

Verification

# Build
cargo build --release

# Test hook handler
echo '{"tool_name":"Bash","tool_input":{"command":"git status"}}' | ./target/release/rtk hook qoder
# → {"hookSpecificOutput":{"updatedInput":{"command":"rtk git status"}}}

# Test project-scoped init
rtk init --agent qoder
# → Creates RTK.md, patches AGENTS.md, writes .qoder/settings.json

# Test global init
rtk init -g --agent qoder
# → Creates ~/.qoder/RTK.md, patches ~/.qoder/settings.json

# Test upgrade from shell script
# (if you previously used the workaround from #1327)
rtk init -g --agent qoder -v
# → "Upgraded Qoder hook from `~/.qoder/hooks/rtk-qoder-hook.sh` to `rtk hook qoder`"

# Run tests
cargo test --bin rtk -- qoder   # 8 tests
cargo test --bin rtk            # 1695 tests (all pass)

@CLAassistant
Copy link
Copy Markdown

CLAassistant commented May 5, 2026

CLA assistant check
All committers have signed the CLA.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants